<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Controller
 * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Front.php 16541 2009-07-07 06:59:03Z bkarwin $
 */


/** Zend_Loader */
require_once 'Zend/Loader.php';

/** Zend_Controller_Action_HelperBroker */
require_once 'Zend/Controller/Action/HelperBroker.php';

/** Zend_Controller_Plugin_Broker */
require_once 'Zend/Controller/Plugin/Broker.php';

/**
 * @category   Zend
 * @package    Zend_Controller
 * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Controller_Front
{
	/**
	 * Base URL
	 * @var string
	 */
	protected $_baseUrl = null;

	/**
	 * Directory|ies where controllers are stored
	 *
	 * @var string|array
	 */
	protected $_controllerDir = null;

	/**
	 * Instance of Zend_Controller_Dispatcher_Interface
	 * @var Zend_Controller_Dispatcher_Interface
	 */
	protected $_dispatcher = null;

	/**
	 * Singleton instance
	 *
	 * Marked only as protected to allow extension of the class. To extend,
	 * simply override {@link getInstance()}.
	 *
	 * @var Zend_Controller_Front
	 */
	protected static $_instance = null;

	/**
	 * Array of invocation parameters to use when instantiating action
	 * controllers
	 * @var array
	 */
	protected $_invokeParams = array();

	/**
	 * Subdirectory within a module containing controllers; defaults to 'controllers'
	 * @var string
	 */
	protected $_moduleControllerDirectoryName = 'controllers';

	/**
	 * Instance of Zend_Controller_Plugin_Broker
	 * @var Zend_Controller_Plugin_Broker
	 */
	protected $_plugins = null;

	/**
	 * Instance of Zend_Controller_Request_Abstract
	 * @var Zend_Controller_Request_Abstract
	 */
	protected $_request = null;

	/**
	 * Instance of Zend_Controller_Response_Abstract
	 * @var Zend_Controller_Response_Abstract
	 */
	protected $_response = null;

	/**
	 * Whether or not to return the response prior to rendering output while in
	 * {@link dispatch()}; default is to send headers and render output.
	 * @var boolean
	 */
	protected $_returnResponse = false;

	/**
	 * Instance of Zend_Controller_Router_Interface
	 * @var Zend_Controller_Router_Interface
	 */
	protected $_router = null;

	/**
	 * Whether or not exceptions encountered in {@link dispatch()} should be
	 * thrown or trapped in the response object
	 * @var boolean
	 */
	protected $_throwExceptions = false;

	/**
	 * Constructor
	 *
	 * Instantiate using {@link getInstance()}; front controller is a singleton
	 * object.
	 *
	 * Instantiates the plugin broker.
	 *
	 * @return void
	 */
	protected function __construct()
	{
		$this->_plugins = new Zend_Controller_Plugin_Broker();
	}

	/**
	 * Enforce singleton; disallow cloning
	 *
	 * @return void
	 */
	private function __clone()
	{
	}

	/**
	 * Singleton instance
	 *
	 * @return Zend_Controller_Front
	 */
	public static function getInstance()
	{
		if (null === self::$_instance) {
			self::$_instance = new self();
		}

		return self::$_instance;
	}

	/**
	 * Resets all object properties of the singleton instance
	 *
	 * Primarily used for testing; could be used to chain front controllers.
	 *
	 * Also resets action helper broker, clearing all registered helpers.
	 *
	 * @return void
	 */
	public function resetInstance()
	{
		$reflection = new ReflectionObject($this);
		foreach ($reflection->getProperties() as $property) {
			$name = $property->getName();
			switch ($name) {
				case '_instance':
					break;
				case '_controllerDir':
				case '_invokeParams':
					$this->{$name} = array();
					break;
				case '_plugins':
					$this->{$name} = new Zend_Controller_Plugin_Broker();
					break;
				case '_throwExceptions':
				case '_returnResponse':
					$this->{$name} = false;
					break;
				case '_moduleControllerDirectoryName':
					$this->{$name} = 'controllers';
					break;
				default:
					$this->{$name} = null;
					break;
			}
		}
		Zend_Controller_Action_HelperBroker::resetHelpers();
	}

	/**
	 * Convenience feature, calls setControllerDirectory()->setRouter()->dispatch()
	 *
	 * In PHP 5.1.x, a call to a static method never populates $this -- so run()
	 * may actually be called after setting up your front controller.
	 *
	 * @param string|array $controllerDirectory Path to Zend_Controller_Action
	 * controller classes or array of such paths
	 * @return void
	 * @throws Zend_Controller_Exception if called from an object instance
	 */
	public static function run($controllerDirectory)
	{
		self::getInstance()
		->setControllerDirectory($controllerDirectory)
		->dispatch();
	}

	/**
	 * Add a controller directory to the controller directory stack
	 *
	 * If $args is presented and is a string, uses it for the array key mapping
	 * to the directory specified.
	 *
	 * @param string $directory
	 * @param string $module Optional argument; module with which to associate directory. If none provided, assumes 'default'
	 * @return Zend_Controller_Front
	 * @throws Zend_Controller_Exception if directory not found or readable
	 */
	public function addControllerDirectory($directory, $module = null)
	{
		$this->getDispatcher()->addControllerDirectory($directory, $module);
		return $this;
	}

	/**
	 * Set controller directory
	 *
	 * Stores controller directory(ies) in dispatcher. May be an array of
	 * directories or a string containing a single directory.
	 *
	 * @param string|array $directory Path to Zend_Controller_Action controller
	 * classes or array of such paths
	 * @param  string $module Optional module name to use with string $directory
	 * @return Zend_Controller_Front
	 */
	public function setControllerDirectory($directory, $module = null)
	{
		$this->getDispatcher()->setControllerDirectory($directory, $module);
		return $this;
	}

	/**
	 * Retrieve controller directory
	 *
	 * Retrieves:
	 * - Array of all controller directories if no $name passed
	 * - String path if $name passed and exists as a key in controller directory array
	 * - null if $name passed but does not exist in controller directory keys
	 *
	 * @param  string $name Default null
	 * @return array|string|null
	 */
	public function getControllerDirectory($name = null)
	{
		return $this->getDispatcher()->getControllerDirectory($name);
	}

	/**
	 * Remove a controller directory by module name
	 *
	 * @param  string $module
	 * @return bool
	 */
	public function removeControllerDirectory($module)
	{
		return $this->getDispatcher()->removeControllerDirectory($module);
	}

	/**
	 * Specify a directory as containing modules
	 *
	 * Iterates through the directory, adding any subdirectories as modules;
	 * the subdirectory within each module named after {@link $_moduleControllerDirectoryName}
	 * will be used as the controller directory path.
	 *
	 * @param  string $path
	 * @return Zend_Controller_Front
	 */
	public function addModuleDirectory($path)
	{
		try{
			$dir = new DirectoryIterator($path);
		}catch(Exception $e){
			require_once 'Zend/Controller/Exception.php';
			throw new Zend_Controller_Exception("Directory $path not readable");
		}
		foreach ($dir as $file) {
			if ($file->isDot() || !$file->isDir()) {
				continue;
			}

			$module    = $file->getFilename();

			// Don't use SCCS directories as modules
			if (preg_match('/^[^a-z]/i', $module) || ('CVS' == $module)) {
				continue;
			}

			$moduleDir = $file->getPathname() . DIRECTORY_SEPARATOR . $this->getModuleControllerDirectoryName();
			$this->addControllerDirectory($moduleDir, $module);
		}

		return $this;
	}

	/**
	 * Return the path to a module directory (but not the controllers directory within)
	 *
	 * @param  string $module
	 * @return string|null
	 */
	public function getModuleDirectory($module = null)
	{
		if (null === $module) {
			$request = $this->getRequest();
			if (null !== $request) {
				$module = $this->getRequest()->getModuleName();
			}
			if (empty($module)) {
				$module = $this->getDispatcher()->getDefaultModule();
			}
		}

		$controllerDir = $this->getControllerDirectory($module);

		if ((null === $controllerDir) || !is_string($controllerDir)) {
			return null;
		}

		return dirname($controllerDir);
	}

	/**
	 * Set the directory name within a module containing controllers
	 *
	 * @param  string $name
	 * @return Zend_Controller_Front
	 */
	public function setModuleControllerDirectoryName($name = 'controllers')
	{
		$this->_moduleControllerDirectoryName = (string) $name;

		return $this;
	}

	/**
	 * Return the directory name within a module containing controllers
	 *
	 * @return string
	 */
	public function getModuleControllerDirectoryName()
	{
		return $this->_moduleControllerDirectoryName;
	}

	/**
	 * Set the default controller (unformatted string)
	 *
	 * @param string $controller
	 * @return Zend_Controller_Front
	 */
	public function setDefaultControllerName($controller)
	{
		$dispatcher = $this->getDispatcher();
		$dispatcher->setDefaultControllerName($controller);
		return $this;
	}

	/**
	 * Retrieve the default controller (unformatted string)
	 *
	 * @return string
	 */
	public function getDefaultControllerName()
	{
		return $this->getDispatcher()->getDefaultControllerName();
	}

	/**
	 * Set the default action (unformatted string)
	 *
	 * @param string $action
	 * @return Zend_Controller_Front
	 */
	public function setDefaultAction($action)
	{
		$dispatcher = $this->getDispatcher();
		$dispatcher->setDefaultAction($action);
		return $this;
	}

	/**
	 * Retrieve the default action (unformatted string)
	 *
	 * @return string
	 */
	public function getDefaultAction()
	{
		return $this->getDispatcher()->getDefaultAction();
	}

	/**
	 * Set the default module name
	 *
	 * @param string $module
	 * @return Zend_Controller_Front
	 */
	public function setDefaultModule($module)
	{
		$dispatcher = $this->getDispatcher();
		$dispatcher->setDefaultModule($module);
		return $this;
	}

	/**
	 * Retrieve the default module
	 *
	 * @return string
	 */
	public function getDefaultModule()
	{
		return $this->getDispatcher()->getDefaultModule();
	}

	/**
	 * Set request class/object
	 *
	 * Set the request object.  The request holds the request environment.
	 *
	 * If a class name is provided, it will instantiate it
	 *
	 * @param string|Zend_Controller_Request_Abstract $request
	 * @throws Zend_Controller_Exception if invalid request class
	 * @return Zend_Controller_Front
	 */
	public function setRequest($request)
	{
		if (is_string($request)) {
			if (!class_exists($request)) {
				require_once 'Zend/Loader.php';
				Zend_Loader::loadClass($request);
			}
			$request = new $request();
		}
		if (!$request instanceof Zend_Controller_Request_Abstract) {
			require_once 'Zend/Controller/Exception.php';
			throw new Zend_Controller_Exception('Invalid request class');
		}

		$this->_request = $request;

		return $this;
	}

	/**
	 * Return the request object.
	 *
	 * @return null|Zend_Controller_Request_Abstract
	 */
	public function getRequest()
	{
		return $this->_request;
	}

	/**
	 * Set router class/object
	 *
	 * Set the router object.  The router is responsible for mapping
	 * the request to a controller and action.
	 *
	 * If a class name is provided, instantiates router with any parameters
	 * registered via {@link setParam()} or {@link setParams()}.
	 *
	 * @param string|Zend_Controller_Router_Interface $router
	 * @throws Zend_Controller_Exception if invalid router class
	 * @return Zend_Controller_Front
	 */
	public function setRouter($router)
	{
		if (is_string($router)) {
			if (!class_exists($router)) {
				require_once 'Zend/Loader.php';
				Zend_Loader::loadClass($router);
			}
			$router = new $router();
		}

		if (!$router instanceof Zend_Controller_Router_Interface) {
			require_once 'Zend/Controller/Exception.php';
			throw new Zend_Controller_Exception('Invalid router class');
		}

		$router->setFrontController($this);
		$this->_router = $router;

		return $this;
	}

	/**
	 * Return the router object.
	 *
	 * Instantiates a Zend_Controller_Router_Rewrite object if no router currently set.
	 *
	 * @return Zend_Controller_Router_Interface
	 */
	public function getRouter()
	{
		if (null == $this->_router) {
			require_once 'Zend/Controller/Router/Rewrite.php';
			$this->setRouter(new Zend_Controller_Router_Rewrite());
		}

		return $this->_router;
	}

	/**
	 * Set the base URL used for requests
	 *
	 * Use to set the base URL segment of the REQUEST_URI to use when
	 * determining PATH_INFO, etc. Examples:
	 * - /admin
	 * - /myapp
	 * - /subdir/index.php
	 *
	 * Note that the URL should not include the full URI. Do not use:
	 * - http://example.com/admin
	 * - http://example.com/myapp
	 * - http://example.com/subdir/index.php
	 *
	 * If a null value is passed, this can be used as well for autodiscovery (default).
	 *
	 * @param string $base
	 * @return Zend_Controller_Front
	 * @throws Zend_Controller_Exception for non-string $base
	 */
	public function setBaseUrl($base = null)
	{
		if (!is_string($base) && (null !== $base)) {
			require_once 'Zend/Controller/Exception.php';
			throw new Zend_Controller_Exception('Rewrite base must be a string');
		}

		$this->_baseUrl = $base;

		if ((null !== ($request = $this->getRequest())) && (method_exists($request, 'setBaseUrl'))) {
			$request->setBaseUrl($base);
		}

		return $this;
	}

	/**
	 * Retrieve the currently set base URL
	 *
	 * @return string
	 */
	public function getBaseUrl()
	{
		$request = $this->getRequest();
		if ((null !== $request) && method_exists($request, 'getBaseUrl')) {
			return $request->getBaseUrl();
		}

		return $this->_baseUrl;
	}

	/**
	 * Set the dispatcher object.  The dispatcher is responsible for
	 * taking a Zend_Controller_Dispatcher_Token object, instantiating the controller, and
	 * call the action method of the controller.
	 *
	 * @param Zend_Controller_Dispatcher_Interface $dispatcher
	 * @return Zend_Controller_Front
	 */
	public function setDispatcher(Zend_Controller_Dispatcher_Interface $dispatcher)
	{
		$this->_dispatcher = $dispatcher;
		return $this;
	}

	/**
	 * Return the dispatcher object.
	 *
	 * @return Zend_Controller_Dispatcher_Interface
	 */
	public function getDispatcher()
	{
		/**
		 * Instantiate the default dispatcher if one was not set.
		 */
		if (!$this->_dispatcher instanceof Zend_Controller_Dispatcher_Interface) {
			require_once 'Zend/Controller/Dispatcher/Standard.php';
			$this->_dispatcher = new Zend_Controller_Dispatcher_Standard();
		}
		return $this->_dispatcher;
	}

	/**
	 * Set response class/object
	 *
	 * Set the response object.  The response is a container for action
	 * responses and headers. Usage is optional.
	 *
	 * If a class name is provided, instantiates a response object.
	 *
	 * @param string|Zend_Controller_Response_Abstract $response
	 * @throws Zend_Controller_Exception if invalid response class
	 * @return Zend_Controller_Front
	 */
	public function setResponse($response)
	{
		if (is_string($response)) {
			if (!class_exists($response)) {
				require_once 'Zend/Loader.php';
				Zend_Loader::loadClass($response);
			}
			$response = new $response();
		}
		if (!$response instanceof Zend_Controller_Response_Abstract) {
			require_once 'Zend/Controller/Exception.php';
			throw new Zend_Controller_Exception('Invalid response class');
		}

		$this->_response = $response;

		return $this;
	}

	/**
	 * Return the response object.
	 *
	 * @return null|Zend_Controller_Response_Abstract
	 */
	public function getResponse()
	{
		return $this->_response;
	}

	/**
	 * Add or modify a parameter to use when instantiating an action controller
	 *
	 * @param string $name
	 * @param mixed $value
	 * @return Zend_Controller_Front
	 */
	public function setParam($name, $value)
	{
		$name = (string) $name;
		$this->_invokeParams[$name] = $value;
		return $this;
	}

	/**
	 * Set parameters to pass to action controller constructors
	 *
	 * @param array $params
	 * @return Zend_Controller_Front
	 */
	public function setParams(array $params)
	{
		$this->_invokeParams = array_merge($this->_invokeParams, $params);
		return $this;
	}

	/**
	 * Retrieve a single parameter from the controller parameter stack
	 *
	 * @param string $name
	 * @return mixed
	 */
	public function getParam($name)
	{
		if(isset($this->_invokeParams[$name])) {
			return $this->_invokeParams[$name];
		}

		return null;
	}

	/**
	 * Retrieve action controller instantiation parameters
	 *
	 * @return array
	 */
	public function getParams()
	{
		return $this->_invokeParams;
	}

	/**
	 * Clear the controller parameter stack
	 *
	 * By default, clears all parameters. If a parameter name is given, clears
	 * only that parameter; if an array of parameter names is provided, clears
	 * each.
	 *
	 * @param null|string|array single key or array of keys for params to clear
	 * @return Zend_Controller_Front
	 */
	public function clearParams($name = null)
	{
		if (null === $name) {
			$this->_invokeParams = array();
		} elseif (is_string($name) && isset($this->_invokeParams[$name])) {
			unset($this->_invokeParams[$name]);
		} elseif (is_array($name)) {
			foreach ($name as $key) {
				if (is_string($key) && isset($this->_invokeParams[$key])) {
					unset($this->_invokeParams[$key]);
				}
			}
		}

		return $this;
	}

	/**
	 * Register a plugin.
	 *
	 * @param  Zend_Controller_Plugin_Abstract $plugin
	 * @param  int $stackIndex Optional; stack index for plugin
	 * @return Zend_Controller_Front
	 */
	public function registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)
	{
		$this->_plugins->registerPlugin($plugin, $stackIndex);
		return $this;
	}

	/**
	 * Unregister a plugin.
	 *
	 * @param  string|Zend_Controller_Plugin_Abstract $plugin Plugin class or object to unregister
	 * @return Zend_Controller_Front
	 */
	public function unregisterPlugin($plugin)
	{
		$this->_plugins->unregisterPlugin($plugin);
		return $this;
	}

	/**
	 * Is a particular plugin registered?
	 *
	 * @param  string $class
	 * @return bool
	 */
	public function hasPlugin($class)
	{
		return $this->_plugins->hasPlugin($class);
	}

	/**
	 * Retrieve a plugin or plugins by class
	 *
	 * @param  string $class
	 * @return false|Zend_Controller_Plugin_Abstract|array
	 */
	public function getPlugin($class)
	{
		return $this->_plugins->getPlugin($class);
	}

	/**
	 * Retrieve all plugins
	 *
	 * @return array
	 */
	public function getPlugins()
	{
		return $this->_plugins->getPlugins();
	}

	/**
	 * Set the throwExceptions flag and retrieve current status
	 *
	 * Set whether exceptions encounted in the dispatch loop should be thrown
	 * or caught and trapped in the response object.
	 *
	 * Default behaviour is to trap them in the response object; call this
	 * method to have them thrown.
	 *
	 * Passing no value will return the current value of the flag; passing a
	 * boolean true or false value will set the flag and return the current
	 * object instance.
	 *
	 * @param boolean $flag Defaults to null (return flag state)
	 * @return boolean|Zend_Controller_Front Used as a setter, returns object; as a getter, returns boolean
	 */
	public function throwExceptions($flag = null)
	{
		if ($flag !== null) {
			$this->_throwExceptions = (bool) $flag;
			return $this;
		}

		return $this->_throwExceptions;
	}

	/**
	 * Set whether {@link dispatch()} should return the response without first
	 * rendering output. By default, output is rendered and dispatch() returns
	 * nothing.
	 *
	 * @param boolean $flag
	 * @return boolean|Zend_Controller_Front Used as a setter, returns object; as a getter, returns boolean
	 */
	public function returnResponse($flag = null)
	{
		if (true === $flag) {
			$this->_returnResponse = true;
			return $this;
		} elseif (false === $flag) {
			$this->_returnResponse = false;
			return $this;
		}

		return $this->_returnResponse;
	}

	/**
	 * Dispatch an HTTP request to a controller/action.
	 *
	 * @param Zend_Controller_Request_Abstract|null $request
	 * @param Zend_Controller_Response_Abstract|null $response
	 * @return void|Zend_Controller_Response_Abstract Returns response object if returnResponse() is true
	 */
	public function dispatch(Zend_Controller_Request_Abstract $request = null, Zend_Controller_Response_Abstract $response = null)
	{
		if (!$this->getParam('noErrorHandler') && !$this->_plugins->hasPlugin('Zend_Controller_Plugin_ErrorHandler')) {
			// Register with stack index of 100
			require_once 'Zend/Controller/Plugin/ErrorHandler.php';
			$this->_plugins->registerPlugin(new Zend_Controller_Plugin_ErrorHandler(), 100);
		}

		if (!$this->getParam('noViewRenderer') && !Zend_Controller_Action_HelperBroker::hasHelper('viewRenderer')) {
			require_once 'Zend/Controller/Action/Helper/ViewRenderer.php';
			Zend_Controller_Action_HelperBroker::getStack()->offsetSet(-80, new Zend_Controller_Action_Helper_ViewRenderer());
		}

		/**
		 * Instantiate default request object (HTTP version) if none provided
		 */
		if (null !== $request) {
			$this->setRequest($request);
		} elseif ((null === $request) && (null === ($request = $this->getRequest()))) {
			require_once 'Zend/Controller/Request/Http.php';
			$request = new Zend_Controller_Request_Http();
			$this->setRequest($request);
		}

		/**
		 * Set base URL of request object, if available
		 */
		if (is_callable(array($this->_request, 'setBaseUrl'))) {
			if (null !== $this->_baseUrl) {
				$this->_request->setBaseUrl($this->_baseUrl);
			}
		}

		/**
		 * Instantiate default response object (HTTP version) if none provided
		 */
		if (null !== $response) {
			$this->setResponse($response);
		} elseif ((null === $this->_response) && (null === ($this->_response = $this->getResponse()))) {
			require_once 'Zend/Controller/Response/Http.php';
			$response = new Zend_Controller_Response_Http();
			$this->setResponse($response);
		}

		/**
		 * Register request and response objects with plugin broker
		 */
		$this->_plugins
		->setRequest($this->_request)
		->setResponse($this->_response);

		/**
		 * Initialize router
		 */
		$router = $this->getRouter();
		$router->setParams($this->getParams());

		/**
		 * Initialize dispatcher
		 */
		$dispatcher = $this->getDispatcher();
		$dispatcher->setParams($this->getParams())
		->setResponse($this->_response);

		// Begin dispatch
		try {
			/**
			 * Route request to controller/action, if a router is provided
			 */

			/**
			 * Notify plugins of router startup
			 */
			$this->_plugins->routeStartup($this->_request);

			$router->route($this->_request);

			/**
			 * Notify plugins of router completion
			 */
			$this->_plugins->routeShutdown($this->_request);

			/**
			 * Notify plugins of dispatch loop startup
			 */
			$this->_plugins->dispatchLoopStartup($this->_request);

			/**
			 *  Attempt to dispatch the controller/action. If the $this->_request
			 *  indicates that it needs to be dispatched, move to the next
			 *  action in the request.
			 */
			do {
				$this->_request->setDispatched(true);

				/**
				 * Notify plugins of dispatch startup
				 */
				$this->_plugins->preDispatch($this->_request);

				/**
				 * Skip requested action if preDispatch() has reset it
				 */
				if (!$this->_request->isDispatched()) {
					continue;
				}

				/**
				 * Dispatch request
				 */
				try {
					$dispatcher->dispatch($this->_request, $this->_response);
				} catch (Exception $e) {
					if ($this->throwExceptions()) {
						throw $e;
					}
					$this->_response->setException($e);
				}

				/**
				 * Notify plugins of dispatch completion
				 */
				$this->_plugins->postDispatch($this->_request);
			} while (!$this->_request->isDispatched());
		} catch (Exception $e) {
			if ($this->throwExceptions()) {
				throw $e;
			}

			$this->_response->setException($e);
		}

		/**
		 * Notify plugins of dispatch loop completion
		 */
		try {
			$this->_plugins->dispatchLoopShutdown();
		} catch (Exception $e) {
			if ($this->throwExceptions()) {
				throw $e;
			}

			$this->_response->setException($e);
		}

		if ($this->returnResponse()) {
			return $this->_response;
		}

		$this->_response->sendResponse();
	}
}
